home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / tk / tkwidget.c < prev   
Encoding:
C/C++ Source or Header  |  1996-05-17  |  10.1 KB  |  453 lines

  1. /* Widgets for the Midnight Commander, Tk interface code
  2.    Copyright (C) 1994 Radek Doulik
  3.    Copyright (C) 1994, 1995 Miguel de Icaza
  4.    Copyright (C) 1995 Jakub Jelinek
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.    TODO: Destroy all the command names that are created for each
  21.    widget during runtime.
  22.  
  23.  */
  24. #include <config.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <ctype.h>
  29. #include "tkmain.h"
  30. #include "dlg.h"
  31.  
  32. static char
  33. widget_number (Widget *w)
  34. {
  35.     Dlg_head *h = w->parent;
  36.     const int count = h->count;
  37.     Widget_Item *item;
  38.     int i;
  39.  
  40.     item = h->first;
  41.     for (i = 0; i < count; i++){
  42.     if (item->widget == w)
  43.         return i;
  44.     item = item->next;
  45.     }
  46.     /* Actually, if we get this far, this message should not appear */
  47.     fprintf (stderr, "Inconsistent widget\n");
  48.     exit (1);
  49. }
  50.  
  51. /* Returns a new command prefixed with an x:
  52.    x.query.$the_frame.b0
  53.  
  54.    for the command of the query dialog box button 0
  55.  
  56.    This allow us to control the widget with the command:
  57.    .query.$the_frame.b0
  58.    
  59.    and to access the C code callback with the:
  60.    x.query.$the_frame.b0
  61.    command.
  62. */
  63. char *
  64. tk_new_command (widget_data parent, void *widget,
  65.                tcl_callback callback, char id)
  66. {
  67.     char buffer [12];
  68.     Widget *w = (Widget *) widget;
  69.     char *cmd, *format; 
  70.  
  71.     if (((char *) parent) [1] == 0)
  72.     format = "%s%c%d";
  73.     else
  74.     format = ".%s%c%d";
  75.  
  76.     /* wdata holds the frame information, it will be replaced with the
  77.      * the widget command name
  78.      */
  79.     sprintf (buffer, format, w->frame, id, widget_number (w));
  80.     cmd = copy_strings ("x", (char *)parent, buffer, 0);
  81.     w->wdata = (widget_data) cmd;
  82.  
  83.     if (callback)
  84.     Tcl_CreateCommand (interp, cmd, callback, w, NULL);
  85.     return cmd;
  86. }
  87.  
  88.  
  89. /* Button routines */
  90.  
  91. /* Called from the Tcl/Tk program when a button has been pressed */
  92. static int
  93. tk_button_callback (ClientData cd, Tcl_Interp *interp, int argc, char *argv [])
  94. {
  95.     WButton *b  = (WButton *) cd;
  96.     Dlg_head *h = (Dlg_head *) b->widget.parent;
  97.     int stop = 0;
  98.     
  99.     if (b->callback)
  100.     stop = (*b->callback)(b->action, b->callback_data);
  101.     if (!b->callback || stop){
  102.     h->running = 0;
  103.     h->ret_value = b->action;
  104.     }
  105.     return TCL_OK;
  106. }
  107.  
  108. /* Removes the [ and ] from the text mode button version */
  109.  
  110. static char *
  111. clean_button (char *text)
  112. {
  113.     static char buffer [20];
  114.     char *p, *q;
  115.  
  116.     if ((strlen (text) + 1) >= sizeof (buffer)){
  117.     return text;
  118.     }
  119.     strcpy (buffer, text);
  120.     for (p = buffer; *p == ' ' || *p == '['; p++)
  121.     ;
  122.     for (q = buffer + strlen (buffer); q > buffer && 
  123.         (!*q || *q == ' ' || *q == ']'); q--);
  124.     *(++q) = 0;
  125.     
  126.     return p;
  127. }
  128.                
  129. void
  130. x_button_set (WButton *b, char *text)
  131. {
  132.     char *cmd = wtcl_cmd (b->widget);
  133.     
  134.     tk_evalf ("%s configure -text {%s}", cmd+1, clean_button (text));
  135. }
  136.  
  137. /* Creates the button $parent.$newname and executes $newname command */
  138. int
  139. x_create_button (Dlg_head *h, widget_data parent, WButton *b)
  140. {
  141.     char *cmd;
  142.     
  143.     cmd = tk_new_command (parent, b, tk_button_callback, 'b');
  144.     tk_evalf ("newbutton %s %s {%s}", cmd+1, cmd, clean_button (b->text));
  145.     return 1;
  146. }
  147.  
  148.  
  149.  
  150. /* Radio button routines */
  151. static int
  152. tk_radio_callback (ClientData cd, Tcl_Interp *interp, int argc, char *argv [])
  153. {
  154.     WRadio   *r = (WRadio *) cd;
  155.  
  156.     if (STREQ (argv [1], "select")){
  157.     r->pos = r->sel = atoi (argv [2]);
  158.     }
  159.     (r->widget.callback)(r->widget.parent, r, WIDGET_KEY, ' ');
  160.     return TCL_OK;
  161. }
  162.  
  163. int
  164. x_create_radio (Dlg_head *h, widget_data parent, WRadio *r)
  165. {
  166.     int i;
  167.     char *cmd;
  168.  
  169.     cmd = tk_new_command (parent, r, tk_radio_callback, 'r');
  170.     tk_evalf ("newradio %s", cmd+1);
  171.     
  172.     for (i = 0; i < r->count; i++){
  173.     tk_evalf ("radio_item %d {%s} %s %d", i, r->texts [i], cmd,
  174.         r->sel == i);
  175.     }
  176.     return 1;
  177. }
  178.  
  179. /* Checkbuttons routines */
  180.  
  181. static int
  182. tk_check_callback (ClientData cd, Tcl_Interp *interp, int argc, char *argv [])
  183. {
  184.     WCheck   *c = (WCheck *) cd;
  185.     Dlg_head *h = c->widget.parent;
  186.  
  187.     (*c->widget.callback)(h, c, WIDGET_KEY, ' ');
  188.     return TCL_OK;
  189. }
  190.  
  191. int
  192. x_create_check (Dlg_head *h, widget_data parent, WCheck *c)
  193. {
  194.     char *cmd;
  195.  
  196.     cmd = tk_new_command (parent, c, tk_check_callback, 'c');
  197.     tk_evalf ("newcheck %s %s {%s} %d", cmd+1, cmd, c->text, c->state);
  198.  
  199.     return 1;
  200. }
  201.  
  202.  
  203. /* Input line */
  204.  
  205. /* This callback command accepts the following commands:
  206. ** 
  207. ** $win mouse x-position
  208. ** $win setmark x-position
  209. */
  210. static int
  211. tk_input_callback (ClientData cd, Tcl_Interp *interp, int argc, char *av [])
  212. {
  213.     Gpm_Event e;
  214.     WInput *in = (WInput *) cd;
  215.     
  216.     if (strcmp (av [1], "mouse") == 0){
  217.     e.x = atoi (av [2]) + 1;
  218.     e.y = 0;
  219.     e.type = GPM_DOWN;
  220.     input_event (&e, (WInput *) cd);
  221.     return TCL_OK;
  222.     } else if (strcmp (av [1], "setmark") == 0){
  223.     in->mark = in->point;
  224.     return TCL_OK;
  225.     }
  226.     
  227.     return TCL_OK;
  228. }
  229.  
  230. void
  231. tk_update_input (WInput *in)
  232. {
  233.     char *name = wtcl_cmd (in->widget);
  234.     int  p;
  235.     
  236.     if (!name)
  237.     return;
  238.  
  239.     name++;
  240.     if (in->is_password){
  241.     tk_evalf ("%s delete 0 end", name);
  242.     tk_evalf ("%s insert end {*secret*}", name);
  243.     p = 9;
  244.     } else {
  245.     tk_evalf ("entry_save_sel %s", name);
  246.     if (in->inserted_one && isascii (in->inserted_one) && in->inserted_one > ' '){
  247.         tk_evalf ("%s insert insert {%c}", name, in->inserted_one);
  248.         in->inserted_one = 0;
  249.     } else {
  250.         tk_evalf ("%s delete 0 end", name);
  251.         tk_evalf ("%s insert end {%s}", name, in->buffer);
  252.     }
  253.     p = in->point;
  254.     }
  255.     tk_evalf ("%s icursor %d; entry_restore_sel %s", name, p, name);
  256. }
  257.  
  258. int
  259. x_create_input (Dlg_head *h, widget_data parent, WInput *in)
  260. {
  261.     char *cmd;
  262.  
  263.     cmd = tk_new_command (parent, in, tk_input_callback, 'i');
  264.     tk_evalf ("newinput %s {%s}", cmd+1, in->buffer ? in->buffer: "");
  265.     return 1;
  266. }
  267.  
  268. void
  269. x_listbox_select_nth (WListbox *l, int nth)
  270. {
  271.     if (!wtcl_cmd (l->widget))
  272.     return;
  273.     
  274.     tk_evalf ("listbox_sel %s %d", wtk_win (l->widget), nth);
  275. }
  276.  
  277. void
  278. x_listbox_delete_nth (WListbox *l, int nth)
  279. {
  280.     tk_evalf ("%s delete %d", wtk_win (l->widget), nth);
  281. }
  282.  
  283. int
  284. x_create_listbox (Dlg_head *h, widget_data parent, WListbox *l)
  285. {
  286.     char *cmd;
  287.     int  i;
  288.     WLEntry *e;
  289.     
  290.     cmd = tk_new_command (parent, l, 0, 'x');
  291.     tk_evalf ("listbox %s -width %d -selectmode single", cmd+1, l->widget.cols);
  292.  
  293.     /* As Jakub said on his very fine xvwidget.c: the user could add some
  294.      * entries to the listbox before the tk-listbox was created, so we have
  295.      * to add it manually :-)
  296.      */
  297.     i = 0;
  298.     if ((e = l->list) == NULL)
  299.     return 1;
  300.  
  301.     do {
  302.     tk_evalf ("%s insert %d {%s}", cmd+1, i, e->text);
  303.     if (e == l->current)
  304.         x_listbox_select_nth (l, i);
  305.     e = e->next;
  306.     i++;
  307.     } while (e != l->list);
  308.     return 1;
  309. }
  310.  
  311. void
  312. x_list_insert (WListbox *l, WLEntry *p, WLEntry *e)
  313. {
  314.     int i;
  315.     char *t = e->text;
  316.  
  317.     if (wtcl_cmd (l->widget) == NULL)
  318.     return;
  319.  
  320.     for (i = 0; p != NULL && p != e; e = e->next, i++)
  321.     ;
  322.     tk_evalf ("%s insert %d {%s}", wtk_win (l->widget), i-1, t);
  323. }
  324.  
  325. int
  326. x_create_label (Dlg_head *g, widget_data parent, WLabel *l)
  327. {
  328.     char *cmd;
  329.  
  330.     cmd = tk_new_command (parent, l, 0, 'l');
  331.     tk_evalf ("label %s -text {%s}", cmd+1, l->text);
  332.     return 1;
  333. }
  334.  
  335.  
  336. void
  337. x_label_set_text (WLabel *label, char *text)
  338. {
  339.     char *lname;
  340.  
  341.     if (!wtcl_cmd (label->widget))
  342.     return;
  343.     
  344.     tk_evalf ("%s configure -text {%s}", wtk_win (label->widget),
  345.           text ? text : "");
  346. }
  347.  
  348.  
  349. static int
  350. tk_buttonbar_callback (ClientData cd, Tcl_Interp *in, int ac, char *av [])
  351. {
  352.     WButtonBar *bb = (WButtonBar *) cd;
  353.     Dlg_head *h = (Dlg_head *) bb->widget.parent;
  354.     int which = atoi (av [1]);
  355.  
  356.     (*bb->labels [which].function)(bb->labels [which].data);
  357.     return TCL_OK;
  358. }
  359.  
  360. int
  361. x_create_buttonbar (Dlg_head *h, widget_data parent, WButtonBar *bb)
  362. {
  363.     char *cmd;
  364.     int  i;
  365.     
  366.     cmd = tk_new_command (parent, bb, tk_buttonbar_callback, 'n');
  367.     tk_evalf ("frame %s", cmd+1);
  368.     for (i = 0; i < 10; i++){
  369.     tk_evalf ("newbutton %s.%d {%s %d} {%d %s}", cmd+1, i, cmd, i, i+1,
  370.           bb->labels [i].text ? bb->labels [i].text : "");
  371.     tk_evalf ("%s.%d configure -padx 1", cmd+1, i);
  372.     tk_evalf ("pack %s.%d -side left -fill x -expand 1 -ipady 0",
  373.         cmd+1, i);
  374.     }
  375.     return 1;
  376. }
  377.  
  378. void
  379. x_redefine_label (WButtonBar *bb, int idx)
  380. {
  381.     if (!bb->widget.wdata)
  382.     return;
  383.  
  384.     if (!*(char *) bb->widget.wdata)
  385.     return;
  386.     
  387.     if (!bb->labels [idx-1].text)
  388.     return;
  389.     tk_evalf ("%s.%d configure -text {%d %s}",
  390.         wtk_win (bb->widget), idx-1, idx, bb->labels [idx-1].text);
  391. }
  392.  
  393. /* destructor for the Tk widgets */
  394. void
  395. x_destroy_cmd (void *w)
  396. {
  397.     Widget *widget = (Widget *)w;
  398.     
  399.     if (widget->wdata){
  400.     Tcl_DeleteCommand (interp, wtcl_cmd (*widget));
  401.     tk_evalf ("destroy %s", wtk_win (*widget));
  402.     free (wtcl_cmd (*widget));
  403.     }
  404. }
  405.  
  406. int
  407. x_find_buttonbar_check (WButtonBar *bb, Widget *paneletc)
  408. {
  409.     return (strcmp ((char *) bb->widget.wcontainer,
  410.             (char *)paneletc->wcontainer));
  411. }
  412.  
  413. /* The only parameter accepted is the size of the widget width */
  414. static int
  415. tk_gauge_callback (ClientData cd, Tcl_Interp *in, int ac, char *av [])
  416. {
  417.     WGauge *g = (WGauge *) cd;
  418.  
  419.     g->pixels = atoi (av [1]);
  420.     return TCL_OK;
  421. }
  422.  
  423. void
  424. x_create_gauge (Dlg_head *h, widget_data parent, WGauge *g)
  425. {
  426.     char *cmd;
  427.  
  428.     cmd = tk_new_command (parent, g, tk_gauge_callback, 'g');
  429.     tk_evalf ("newgauge %s", cmd+1);
  430. }
  431.  
  432. static void
  433. x_gauge_display (WGauge *g)
  434. {
  435.     tk_evalf ("%s coords gauge 0 0 %d 90", wtk_win (g->widget),
  436.           (int) (g->current*g->pixels)/g->max);
  437. }
  438.  
  439. void
  440. x_gauge_show (WGauge *g)
  441. {
  442.     tk_evalf ("gauge_%s %s", g->shown ? "shown":"hidden", wtk_win (g->widget));
  443.     if (g->shown)
  444.     x_gauge_display (g);
  445. }
  446.  
  447. void
  448. x_gauge_set_value (WGauge *g, int max, int current)
  449. {
  450.     if (g->shown)
  451.     x_gauge_display (g);
  452. }
  453.